package com.javasm.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;

/** 连接池对象
 * @remark:
 */
public class SmDataSource {
    //链表集合 ArrayList与LinkedList
    private static LinkedList<Connection> list=new LinkedList<>(); //连接池堆栈
    private String url; //数据库连接地址
    private String username;
    private String password;
    private Integer initSize;  //数据库连接数

    static{
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public SmDataSource(){

    }
  //获取连接池当前可以连接数量
    public int getSize(){
        return list.size();
    }
   //初始化数据库连接  静态代理
    public void init(){
        for(int i=0;i<initSize;i++){
            try {
                //源对象 source
                Connection source = DriverManager.getConnection(url, username, password);
                //初始化连接时,直接在source对象基础上创建代理对象,放在list集合中.
                Connection proxy  =new ConnectionProxy(source,this);// 静态代理对象 ConnectionProxy（）
                list.addLast(proxy);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    //初始化数据库连接  动态代理
    public void init2(){
        for(int i=0;i<initSize;i++){
            try {
                //源对象 Connection
                Connection source = DriverManager.getConnection(url, username, password);
                //初始化连接时,直接在source对象基础上创建代理对象,放在list集合中.

                //参数1： ClassLoader是一个类加载器，获取ClassLoader对象
                ClassLoader loader = Connection.class.getClassLoader();
                //参数2：提供源对象接口对象
                Class[] interfaces=new Class[]{Connection.class};
                //参数3：InvocationHandler对象  动态代理的核心
                InvocationHandler handler = new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//代理对象newProxyInstance 的invoke（）方法
                        //close方法不在执行Connection源对象的方法
                        String name = method.getName();
                        if("close".equals(name)){
                            //把proxy放回连接池this
                            back((Connection) proxy);
                        }else{
                            return method.invoke(source,args);// 源对象Connection的invoke（）方法
                        }
                        return null;
                    }
                };
                //动态代理
                Connection proxy = (Connection)Proxy.newProxyInstance(loader,interfaces,handler);
                list.addLast(proxy);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

   // pop()方法用于从LinkedList表示的堆栈中删除并返回顶部元素。该方法只是弹出出现在堆栈顶部的元素。此方法类似于LinkedList中的removeFirst方法。
    //返回值：该方法返回由LinkedList表示的堆栈的first(栈顶)值
    public Connection getConnection(){
        Connection source = list.pop(); //连接池用完一个，移除一个，直到用完
        return source;
    }

    //返回数据库连接前，将连接池使用的连接放回连接池中
    public void back(Connection conn){
        list.addLast(conn);
    }

    public static LinkedList<Connection> getList() {
        return list;
    }

    public static void setList(LinkedList<Connection> list) {
        SmDataSource.list = list;
    }

    public Integer getInitSize() {
        return initSize;
    }

    public void setInitSize(Integer initSize) {
        this.initSize = initSize;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
